import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.Map.Entry;

public class E1 {
  /**
   * @param args
   * @throws FileNotFoundException
   * @throws UnsupportedEncodingException
   */
  public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
    // we are going to use map to holder read numbers
    // number is a key and number of occurrences is value
    Map<Integer, Integer> map = new HashMap<Integer, Integer>();
    // if this throw exception just throw it out
    FileInputStream fis = new FileInputStream("integers.txt");
    // this constructor can throw UnsupportedEncodingException
    // however, in this case we are sure that UTF8 is supported encoding
    InputStreamReader isr = new InputStreamReader(fis, "UTF8");
    // this constructor does not throws exception
    BufferedReader br = new BufferedReader(isr);
    // this constructor does not throws exception
    Scanner scanner = new Scanner(br);
    // put all reading code in try finnaly so we can release resources at the end
    try {
      // use scanner with its default settings... like delimiter is any whitespace character
      while (scanner.hasNextInt()) {
        int nextInt = scanner.nextInt();
        Integer occurrences = map.get(nextInt);
        // calculate new value to pup
        occurrences = (null == occurrences ? 1 : occurrences + 1);
        map.put(nextInt, occurrences);
      }
    } finally {
      // this will close at the end FileInputStream opened on integers.txt
      scanner.close();
    }
    // now lets sort by number of occurrences
    Set<Entry<Integer, Integer>> entrySet = map.entrySet();
    // we need list view of the data so latter can sort it with Collections#sort(...) method
    List<Entry<Integer, Integer>> list = new ArrayList<Entry<Integer, Integer>>(entrySet);
    // use collections sort algorithm but with custom comparator
    // note that Collections#sort(...) method will modify the list
    Collections.sort(list, new Comparator<Entry<Integer, Integer>>() {
      @Override
      public int compare(Entry<Integer, Integer> o1, Entry<Integer, Integer> o2) {
        return o1.getValue() - o2.getValue();
      }
    });
    // if this throw exception just throw it out
    FileOutputStream fos = new FileOutputStream("integers.ordered.txt");
    // this constructor can throw UnsupportedEncodingException
    // however, in this case we are sure that UTF8 is supported encoding
    OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF8");
    // this constructor does not throws exception
    BufferedWriter bw = new BufferedWriter(osw);
    // this constructor does not throws exception
    PrintWriter pw = new PrintWriter(bw);
    // write sorted list into txt file, just in case wrap this into try - finally block
    try {
      for (Entry<Integer, Integer> entry : list) {
        pw.format("Looks like %d had %d occurrences!%n", entry.getKey(), entry.getValue());
        System.out.format("Looks like %d had %d occurrences!%n", entry.getKey(), entry.getValue());
      }
    } finally {
      pw.close();
    }
  }
}
